#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include "task.hpp"
#include <sys/wait.h>
#include <sys/types.h>

class _channel
{
public:
    _channel(int wfd, pid_t id, const std::string &name)
        : _wfd(wfd), _subprossid(id), _name(name)
    {
    }
    int _getwfd() { return _wfd; }
    pid_t _getsubprossid() { return _subprossid; }
    std::string _getname() { return _name; }
    void _closechannel()
    {
        close(_wfd);
    }
    void _wait()
    {
        pid_t rid = waitpid(_subprossid, nullptr, 0);
        if (rid > 0)
        {
            std::cout << "wait" << rid << "success" << std::endl;
        }
    }
    ~_channel()
    {
    }

private:
    int _wfd;
    pid_t _subprossid;
    std::string _name;
};



// const & 输入型参数
//  & 输入输出型参数
//  * 输出型参数
void _creat_channelandsub(int num, std::vector<_channel> *channels,task_t task)
{
    for (int i = 0; i < num; i++)
    {
        // 创建管道
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        if (n < 0)
            exit(1); // 创建管道失败

        // 创建子进程
        
        pid_t id = fork();
        if (id == 0)
        {
            if(!channels->empty())
            {
                for(auto channel : *channels)//去除继承下来的多余写端
                {
                    channel._closechannel();
                }
            }
            // child-read
            close(pipefd[1]);
            dup2(pipefd[0],0);
            task();
            close(pipefd[0]);
            exit(0);
        }
        // father-write
        std::string channel_name = "Channel-" + std::to_string(i);
        close(pipefd[0]);
        channels->push_back(_channel(pipefd[1], id, channel_name));
    }
}

int next_channel(int channelsnum)
{
    static int next = 0;
    int channel = next++;
    next %= channelsnum;
    return channel;
}

void _sendtask(_channel &channel, int taskcommand)
{
    write(channel._getwfd(), &taskcommand, sizeof(taskcommand));
}

void _ctrlprocess_once(std::vector<_channel> &channels)
{

    // 通过channel控制子进程
    // 选择任务
    int taskcommand = _selecttask();
    // 选择信道
    int channel_index = next_channel(channels.size());
    // 向信道发送任务
    _sendtask(channels[channel_index], taskcommand);
    std::cout << "channel:" << channels[channel_index]._getname() << " taskcommand:"
              << taskcommand << " subprocess:" << channels[channel_index]._getsubprossid() << std::endl;
    sleep(1);
}

void _ctrlprocess(std::vector<_channel> &channels, int times = -1)
{
    if (times > 0)
    {
        while(times--)
        {
            _ctrlprocess_once(channels);
        }
    }
    else
    {
        while (true)
        {
            _ctrlprocess_once(channels);
        }
    }
    
}

void _closeprocess(std::vector<_channel> &channels)
{
    // for (auto &channel : channels)
    // {
    //     channel._closechannel();
    // }
    // for (auto &channel : channels)
    // {
    //     channel._wait();
    // }
    for (auto &channel : channels)
    {
        channel._closechannel();
        channel._wait();
    }
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        std::cerr << "Usage:" << argv[0] << "prossnum" << std::endl;
        return 1;
    }
    int num = std::stoi(argv[1]);

    std::vector<_channel> channels;
    // 任务初始化
    _inittask();
    // 创建信道和子进程
    _creat_channelandsub(num, &channels,_work);
    // 控制信道和子进程
    _ctrlprocess(channels,8);

    // 回收管道和子进程
    _closeprocess(channels);
    return 0;
}
